/// 降采样服务
///
/// 提供音频数据降采样算法，用于将大量数据点压缩为固定数量的数据点
/// 用于前端波形图渲染优化

/// 输出的固定点数
const OUTPUT_POINTS: usize = 2000;
/// 区间数量（每个区间取 min 和 max，共 2000 个点）
const INTERVALS: usize = 1000;

/// Min-Max 降采样算法
///
/// 将输入的音频数据降采样为固定 2000 个点，采用 Min-Max 策略：
/// - 将数据分成 1000 个区间
/// - 每个区间取最小值和最大值
/// - 交替排列形成 2000 个点的输出
///
/// # 参数
///
/// * `data` - 原始音频数据，f32 类型的切片
///
/// # 返回值
///
/// 返回降采样后的数据，固定 2000 个点。如果输入数据长度 <= 2000，直接返回原数据的副本
///
/// # 示例
///
/// ```
/// let audio_data = vec![1.0; 10000];
/// let downsampled = downsample_min_max(&audio_data);
/// assert_eq!(downsampled.len(), 2000);
/// ```
pub fn downsample_min_max(data: &[f32]) -> Vec<f32> {
    // 边界检查：如果数据为空，返回空数组
    if data.is_empty() {
        return Vec::new();
    }

    // 如果数据长度 <= 2000，直接返回原数据
    if data.len() <= OUTPUT_POINTS {
        return data.to_vec();
    }

    // 预分配结果数组
    let mut result = Vec::with_capacity(OUTPUT_POINTS);

    // 计算每个区间的大小（浮点数，用于精确划分）
    let interval_size = data.len() as f32 / INTERVALS as f32;

    // 遍历每个区间
    for i in 0..INTERVALS {
        // 计算当前区间的起始和结束索引
        let start = (i as f32 * interval_size) as usize;
        let end = ((i + 1) as f32 * interval_size) as usize;

        // 确保 end 不超过数据长度
        let end = end.min(data.len());

        // 边界检查：确保区间有效
        if start >= end {
            // 如果区间无效，使用最后一个有效值填充
            if !result.is_empty() {
                let last_val = result.last().copied().unwrap_or(0.0);
                result.push(last_val);
                result.push(last_val);
            } else {
                result.push(0.0);
                result.push(0.0);
            }
            continue;
        }

        // 获取区间数据
        let interval = &data[start..end];

        // 找出区间内的最小值和最大值
        let mut min_val = interval[0];
        let mut max_val = interval[0];

        for &value in interval.iter().skip(1) {
            if value < min_val {
                min_val = value;
            }
            if value > max_val {
                max_val = value;
            }
        }

        // 将 min 和 max 依次放入结果数组
        result.push(min_val);
        result.push(max_val);
    }

    result
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_empty_data() {
        let data: Vec<f32> = Vec::new();
        let result = downsample_min_max(&data);
        assert_eq!(result.len(), 0);
    }

    #[test]
    fn test_small_data() {
        let data: Vec<f32> = vec![1.0, 2.0, 3.0, 4.0, 5.0];
        let result = downsample_min_max(&data);
        assert_eq!(result.len(), 5);
        assert_eq!(result, data);
    }

    #[test]
    fn test_exact_2000_points() {
        let data: Vec<f32> = vec![1.0; 2000];
        let result = downsample_min_max(&data);
        assert_eq!(result.len(), 2000);
    }

    #[test]
    fn test_large_data() {
        let data: Vec<f32> = (0..10000).map(|i| i as f32).collect();
        let result = downsample_min_max(&data);
        assert_eq!(result.len(), 2000);
    }

    #[test]
    fn test_min_max_correctness() {
        // 创建一个简单的测试数据：每 10 个数为一组，值为 0-9
        let mut data = Vec::new();
        for _ in 0..1000 {
            for i in 0..10 {
                data.push(i as f32);
            }
        }

        let result = downsample_min_max(&data);
        assert_eq!(result.len(), 2000);

        // 验证前几个区间的 min 和 max
        // 每个区间应该包含 10 个数据点（10000 / 1000 = 10）
        // 所以每个区间的 min 应该是 0.0，max 应该是 9.0
        assert_eq!(result[0], 0.0); // 第一个区间的 min
        assert_eq!(result[1], 9.0); // 第一个区间的 max
        assert_eq!(result[2], 0.0); // 第二个区间的 min
        assert_eq!(result[3], 9.0); // 第二个区间的 max
    }

    #[test]
    fn test_ascending_data() {
        let data: Vec<f32> = (0..5000).map(|i| i as f32).collect();
        let result = downsample_min_max(&data);
        assert_eq!(result.len(), 2000);

        // 验证结果是递增的（因为原始数据是递增的）
        for i in 0..result.len() - 1 {
            assert!(result[i] <= result[i + 1]);
        }
    }

    #[test]
    fn test_constant_data() {
        let data: Vec<f32> = vec![5.0; 10000];
        let result = downsample_min_max(&data);
        assert_eq!(result.len(), 2000);

        // 所有值应该都是 5.0
        for &val in &result {
            assert_eq!(val, 5.0);
        }
    }

    #[test]
    fn test_alternating_data() {
        let data: Vec<f32> = (0..10000).map(|i| if i % 2 == 0 { -1.0 } else { 1.0 }).collect();
        let result = downsample_min_max(&data);
        assert_eq!(result.len(), 2000);

        // 每个区间的 min 应该是 -1.0，max 应该是 1.0
        for i in 0..INTERVALS {
            assert_eq!(result[i * 2], -1.0);     // min
            assert_eq!(result[i * 2 + 1], 1.0);  // max
        }
    }

    #[test]
    fn test_not_divisible_by_1000() {
        // 测试数据长度不能被 1000 整除的情况
        let data: Vec<f32> = (0..10001).map(|i| i as f32).collect();
        let result = downsample_min_max(&data);
        assert_eq!(result.len(), 2000);

        // 验证最后一个值应该接近最大值
        assert!(result[1999] >= 9900.0);
    }
}
